package com.views
{
	import com.data.ConnectionDAO;
	import com.models.WorkFlow;
	
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.geom.Point;
	
	import mx.core.UIComponent;
	import com.events.ConnectEvent;
	import mx.controls.Label;
	import flash.events.MouseEvent;

	/**
	 * Klasse zur Darstellung einer Verbindung
	 */
	public class Connection extends UIComponent implements IGraphElement
	{
		private var _initiator:IGraphElement;
		private var _target:IGraphElement;
		private var _text:String;
		private var _sprite:Sprite;
		private var _dataId:String;
		private var _model:WorkFlow;
		private var _selected:Boolean;
		private var _width:int;
		private var _height:int;
		private var _data:ConnectionDAO;
		private var _useProxy:Boolean = false;
		private var _direction:String;
		private var _label:Label;
		private var _bgAlpha:Number = 0;
		
		
		/**
		 * Konstruktor
		 * @param data
		 * @return 
		 * 
		 */
		public function Connection(model:WorkFlow, data:ConnectionDAO)
		{
			_model = model;
			_data = data;
			_initiator = _model.getView(data.initiatorDataId);
			_target = _model.getView(data.targetDataId);
			_text = data.text;
			_dataId = data.dataId;
			_model.addEventListener(ConnectEvent.UPDATE, connectUpdate);
			addEventListener(MouseEvent.ROLL_OVER, rollOverHandler);
			addEventListener(MouseEvent.ROLL_OUT, rollOutHandler);
			addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
			toolTip = data.dataId;
			_model.setConnection(this);
			
		}
		
		/**
		 * Hinzufügen der grundlegenden Elemente dieser Klasse.
		 * Wird genau einmal aufgerufen, dies findet während der
		 * Instanzierung statt.
		 */
		override protected function createChildren():void
		{
			super.createChildren();
			
			_label = new Label();
			_label.width = 100;
			_label.height = 20;
			_label.text = "Beschriftung";
			_sprite = drawConnection();
			addChild(_label);
			addChild(_sprite);
			
		}
		
		/**
		 * Aktualisierung der Anzeige der Verbindung
		 * @param unscaledWidth
		 * @param unscaledHeight
		 * 
		 */
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			super.updateDisplayList(unscaledWidth, unscaledHeight);
			
			var sprite:Sprite = drawConnection();
			removeChild(_sprite);
			_sprite = sprite;
			addChild(_sprite);
			
		}
		
		/**
		 * Zeichnet eine Verbindung
		 * @return 
		 * 
		 */
		protected function drawConnection():Sprite
		{
			var start:UIComponent;
			var end:UIComponent;
			var initiator:IGraphElement;
			var target:IGraphElement;
			
			
			if(_useProxy)
			{
				_useProxy = false;
				if(_direction == "out")
				{
					start = _model.proxy as UIComponent;
					end = _target as UIComponent;
				}
				else
				{
					start = _initiator as UIComponent;
					end = _model.proxy as UIComponent;
				}
			}
			else
			{
				start = _initiator as UIComponent;
				end = _target as UIComponent;
			}
			
			// Berechnungen -------------------------------------------------------------------------------------
			
			//trace(parent.mouseX + "    " + parent.mouseY);
			var initiatorCenter:Point = new Point(
				start.getBounds(parent).x + start.getBounds(parent).width/2,
				start.getBounds(parent).y + start.getBounds(parent).height/2);
			var targetCenter:Point = new Point(
				end.getBounds(parent).x + end.getBounds(parent).width/2,
				end.getBounds(parent).y + end.getBounds(parent).height/2);
			
			var diffY:Number = targetCenter.y - initiatorCenter.y;
			var diffX:Number = targetCenter.x - initiatorCenter.x;		
			var radians:Number = Math.atan2(diffY, diffX);
			var degrees:int = radians * 180 / Math.PI;
				
			var arrow:Sprite = new Sprite();
			arrow.graphics.lineStyle(1, 0xFF0000, 0.5);
			arrow.graphics.moveTo(-7,-5);
    		arrow.graphics.lineTo(0,0);
    		arrow.graphics.lineTo(-7,5);
				
			var sprite:Sprite = new Sprite();
			sprite.graphics.lineStyle(1, 0xFF0000, 0.5);
			
			arrow.rotation = degrees;
			arrow.x = initiatorCenter.x + diffX / 2;
			arrow.y = initiatorCenter.y + diffY / 2;
			
			_label.move(arrow.x, arrow.y);
			
			
			
			sprite.graphics.moveTo(initiatorCenter.x, initiatorCenter.y);
			sprite.graphics.lineTo(targetCenter.x, targetCenter.y);
			
			sprite.addChild(arrow);
			
			
			// mouseOver background hitArea
			var bgArrow:Sprite = new Sprite();
			bgArrow.graphics.lineStyle(7, 0xFF0000, _bgAlpha);
			bgArrow.graphics.moveTo(-7,-5);
    		bgArrow.graphics.lineTo(0,0);
    		bgArrow.graphics.lineTo(-7,5);
				
			var bgSprite:Sprite = new Sprite();
			bgSprite.graphics.lineStyle(7, 0xFF0000, _bgAlpha);
			
			_bgAlpha = 0;
			
			bgSprite.graphics.moveTo(initiatorCenter.x, initiatorCenter.y);
			bgSprite.graphics.lineTo(targetCenter.x, targetCenter.y);
			
			bgArrow.rotation = degrees;
			bgArrow.x = initiatorCenter.x + diffX / 2;
			bgArrow.y = initiatorCenter.y + diffY / 2;
			
			bgSprite.addChild(bgArrow);
			sprite.addChild(bgSprite);
			sprite.hitArea = bgSprite
			 
			 return sprite;
		}
		
		private function connectUpdate(evt:ConnectEvent):void
		{
			var test:* = evt.data["connection"];
			if(_dataId == evt.data["connection"].dataId)
			{
				_useProxy = true;
				_direction = evt.data["direction"];
				invalidateDisplayList();
			}
		}
		
		private function rollOverHandler(evt:MouseEvent):void
		{
			if(_model.tool == "delete")
			{
				_bgAlpha = 0.125;
				invalidateDisplayList();
			}
		}
		
		private function rollOutHandler(evt:MouseEvent):void
		{
			if(!_selected)
			{
				_bgAlpha = 0;
				invalidateDisplayList();
			}
		}
		
		private function mouseDownHandler(evt:MouseEvent):void
		{
			_model.setSelectedElement(this);
		}
		
		/**
		 * Eindeutiger Identifizierer
		 * @return 
		 * 
		 */
		public function get dataId():String
		{
			return _dataId;
		}
		
		public function get selected():Boolean
		{
			return _selected;
		}
		public function set selected(value:Boolean):void
		{
			_selected = value;
			if(_selected)
				_bgAlpha = 0.125;
			else
				_bgAlpha = 0;
			invalidateDisplayList();
		}
		
		public function get background():Sprite
		{
			return null;
		}
		
	}
}